package com.vcms.controller.customer;

import com.vcms.controller.customer.states.*;
import com.vcms.controller.system.MainController;
import com.vcms.exception.VMCSException;
import com.vcms.view.simulation.customer.CustomerPanel;
import com.vcms.view.simulation.system.SimulatorControlPanel;

public class TransactionController {
	// Transaction Controller State
	private TransactionState currentState;
	////////////////////	
	
	private MainController mainController;
	private DispenseController dispenseController;
	private CoinReceiver coinReceiver;
	private ChangeGiver changeGiver;
	private CustomerPanel customerPanel;
	
	private boolean drinkDispensed;
	private boolean changeGiven;
	private int selection;
	private float price;
	private int totalInserted;
	
	private String faultSource;
	
	private char mode;

	public TransactionController(MainController mainController) {
		this.mainController = mainController;
		dispenseController = new DispenseController(this);
		coinReceiver = new CoinReceiver(this);
		changeGiver = new ChangeGiver(this);
		faultSource = null;
		
		// Set the state on creation
		this.transitState(StateFactory.getInstance().create(TransactionState.INITIAL,  this));
		//////////////////
	}
	
	/// Transit to State
	public void transitState(TransactionState toState){
		this.currentState = toState;
		this.printState();
	}
	
	// Prints the current State
	public void printState(){
		if(this.currentState != null){
			this.currentState.printState();
		}else{
			System.out.println("- NULL State -");
		}
	}
	
	// Close down and transit to null state
	public void closeDown() {
		System.out.println("Inside CloseDown Handle - Close Down");
		this.transitState(null);
	}

	public void displayCustomerPanel(char mode) {
		this.setMode(mode);
		this.currentState.handleDisplayCustomerPanel();
	}
	
	public void refreshCustomerPanel() {
		// Have to set the transaction controller to initialize state
		this.currentState.handleRefreshCustomerPanel();
		
		// Transit to INITIAL state
		//this.transitState(StateFactory.getInstance().create(TransactionState.INITIAL, this));
	}

	public void closePanel() {
		customerPanel.dispose();
		
		customerPanel = null;
		
		// Checks if current state is Maintenance state, if not then transit to initialize state
		if(!this.currentState.getClass().isInstance(new MaintenanceState(this))) {
			SimulatorControlPanel scp = mainController.getSimulatorControlPanel();
			scp.setActive(SimulatorControlPanel.ACT_CUSTOMER, true);
			scp.setActive(SimulatorControlPanel.ACT_CUSTOMER_NUMERIC, true);
			scp.setActive(SimulatorControlPanel.ACT_CUSTOMER_ALPHANUMERIC, true);
			
			this.transitState(StateFactory.getInstance().create(TransactionState.INITIAL, this));
		}
		
		return;

	}
	
	public void startTransaction(int identifier){
		this.setSelection(identifier);		
		this.currentState.handleStartTransaction();
		
	}
	
	public void processMoneyReceived(int total){
		this.setTotalInserted(total);
		this.currentState.handleProcessMoneyReceived();
	}
	
	
	public void completeTransaction(){
		this.currentState.handleCompleteTransaction();
		
	}
	
		
	public void terminateTransaction(){
		// Transit to TERMINATE state
		this.transitState(StateFactory.getInstance().create(TransactionState.TERMINATE, this));
		
		this.currentState.handleTerminateTransaction();
		
		// After handling termination, transit to maintainer login
		// Transit to MAINTENANCE state
		this.transitState(StateFactory.getInstance().create(TransactionState.MAINTENANCE, this));
	}
	
	public void terminateFault(Object Source) throws VMCSException{
		this.dispenseController.allowSelection(false);
		
		if(Source.getClass().getName().equalsIgnoreCase("DispenseController")){
			this.setFaultSource("DispenseController");
		}else if(Source.getClass().getName().equalsIgnoreCase("ChangeGiver")){
			this.setFaultSource("ChangeGiver");
		}else if(Source.getClass().getName().equalsIgnoreCase("CoinReceiver")){
			this.setFaultSource("CoinReceiver");
		}
		
		this.transitState(StateFactory.getInstance().create(TransactionState.FAULT, this));
		this.currentState.handleTerminateFault();
	}
	
	public void cancelTransaction(){
		if(!this.currentState.getClass().isInstance(new MaintenanceState(this))) {
			// Transit to TERMINATE state
			this.transitState(StateFactory.getInstance().create(TransactionState.TERMINATE, this));
			
			this.currentState.handleTerminateTransaction();
		}
/*		//stop coin entry
		this.coinReceiver.stopReceive();
		
		//refund money so far entered
		this.coinReceiver.refundCash();	
		
		//active drink selection
		this.dispenseController.allowSelection(true);*/
	}
	
	
	/*GETTER*/
	public MainController getMainControler() {return this.mainController;}
	public CustomerPanel getPanel() {return this.customerPanel;}
	public MainController getMainController() {return mainController;}
	public DispenseController getDispenseController() {return dispenseController;}
	public CoinReceiver getCoinReceiver() {return coinReceiver;}
	public ChangeGiver getChangeGiver() {return changeGiver;}
	public CustomerPanel getCustomerPanel() {return customerPanel;}
	
	public char getMode() { return this.mode; }
	public int getSelection() {return this.selection; }
	public float getPrice() { return this.price; }
	public int getTotalInserted() { return this.totalInserted; }
	public boolean isDrinkDispense() { return this.drinkDispensed; }
	public boolean isChangeGiven() { return this.changeGiven; }
	public String getFaultSource() { return this.faultSource; }
	
	/*SETTER*/
	public void setMode(char mode) { this.mode = mode; }
	public void setSelection(int identifier){ this.selection = identifier; }
	public void setPrice(float price) { this.price = price; }
	public void setTotalInserted(int total) { this.totalInserted = total; }
	public void setDrinkDispense(boolean drinkDispensed) { this.drinkDispensed = drinkDispensed; }
	public void setChangeGiven(boolean changeGiven) { this.changeGiven = changeGiven; }
	public void setFaultSource(String faultSource) { this.faultSource = faultSource; }
	public void setCustomerPanel(CustomerPanel customerPanel) { this.customerPanel = customerPanel; }

}
